package com.chinda.modules.sys.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.chinda.common.page.RPage;
import com.chinda.modules.sys.dao.SysMenuDao;
import com.chinda.modules.sys.dto.SysMenuDTO;
import com.chinda.modules.sys.entity.SysMenuEntity;
import com.chinda.modules.sys.qo.SysMenuQO;
import com.chinda.modules.sys.service.SysMenuService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.stream.Collectors;

/**
 * 菜单管理
 *
 * @author chinda
 * @date 2021-06-16 05:52:51
 */
@Service("sysMenuService")
@Transactional(readOnly = true, rollbackFor = Exception.class)
public class SysMenuServiceImpl extends ServiceImpl<SysMenuDao, SysMenuEntity> implements SysMenuService {

    /**
     * 获取分页信息
     *
     * @param qo
     * @return
     */
    @Override
    public RPage page(SysMenuQO qo) {
        return new RPage(page(qo.getPage(), qo.getQueryWrapper()));
    }

    /**
     * 根据用户id获取菜单
     * @param userId
     * @return
     */
    @Override
    public List<SysMenuEntity> selectSysMenuByUserId(Long userId) {
        return baseMapper.selectSysMenuByUserId(userId);
    }

    /**
     * 清空菜单表
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean truncateMenu() {
        return baseMapper.truncateMenu();
    }

    /**
     * 树形结构菜单
     *
     * @param qo
     * @return
     */
    @Override
    public List<SysMenuDTO> listWithTree(SysMenuQO qo) {
        // 1. 查询所有子分类
        List<SysMenuEntity> sysMenuList = list(qo.getQueryWrapper());
        List<SysMenuDTO> sysMenuDTOList = sysMenuList.stream()
                .map(e -> {
                    SysMenuDTO sysMenuDTO = new SysMenuDTO();
                    BeanUtil.copyProperties(e, sysMenuDTO, CopyOptions.create().ignoreNullValue());
                    return sysMenuDTO;
                })
                .collect(Collectors.toList());

        // 2. 组装父子结构 2.1) 查找一级节点  2.2) 根据一级节点查找子节点
        SysMenuDTO root = new SysMenuDTO();
        root.setMenuId(0L);
        return getTree(root, sysMenuDTOList);
    }

    /**
     * 根据父节点获取子节点
     * @param root
     * @param allNode
     * @return
     */
    private List<SysMenuDTO> getChildren(SysMenuDTO root, List<SysMenuDTO> allNode) {
        return getTree(root, allNode);
    }

    private List<SysMenuDTO> getTree(SysMenuDTO root, List<SysMenuDTO> allNode) {
        return allNode.stream()
                .filter(menu -> root.getMenuId().equals(menu.getParentId()))
                .map(menu -> {
                    menu.setChildren(getChildren(menu, allNode));
                    return menu;
                })
                .sorted((menu1, menu2) -> {
                    Integer sort1 = menu1.getSort();
                    Integer sort2 = menu2.getSort();
                    return (null == sort1 ? 0 : sort1) - (null == sort2 ? 0 : sort2);
                }).collect(Collectors.toList());
    }
}